package com.cskaoyan.controller;

import com.cskaoyan.bean.common.BaseRespVo;
import com.cskaoyan.bean.po.*;
import com.cskaoyan.config.realm.CustomToken;
import com.cskaoyan.mapper.MarketAdminPermissionMapper;
import com.cskaoyan.mapper.MarketPermissionMapper;
import com.cskaoyan.mapper.MarketRoleMapper;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

//shiro整合之后，在做具体的开发
//响应结果都是JSON，Controller组件上我们都用@RestController注解
@RestController
@RequestMapping("admin/auth")
public class AuthController {


    @Autowired
    MarketRoleMapper marketRoleMapper;
    @Autowired
    MarketPermissionMapper marketPermissionMapper;
    @Autowired
    MarketAdminPermissionMapper marketAdminPermissionMapper;

    /**
     * Shiro安全框架 → 视频课程 4个课时 → 认证（登录）
     * 如果参数比较少，类型比较简单的话，使用map来接收也可以
     */
    @PostMapping("login")
    public BaseRespVo<LoginUserData> login(@RequestBody Map map) {
        String username = (String) map.get("username");
        String password = (String) map.get("password");
        // Shiro重构登陆业务
        // Subject登陆
        Subject subject = SecurityUtils.getSubject();
        // login需要一个AuthenticationToken接口类型的值，这里使用的的是该接口的实现类UsernamePasswordToken来封装username和password来生成一个token
        AuthenticationToken authenticationToken = new CustomToken(username, password, "admin");
        // 使用生成的token来做一个登陆的认证
//        try {
        // subject.login最后实际执行的是realm中的doGetAuthenticationInfo方法来做一个认证
        subject.login(authenticationToken);
//        } catch (AuthenticationException e) {
//            // 验证不通过，会包报一个IncorrectCredentialsException异常
////            throw new RuntimeException(e);
//            BaseRespVo baseRespVo = new BaseRespVo();
//            baseRespVo.setErrno(605);
//            baseRespVo.setErrmsg("账户和密码不匹配");
//            return baseRespVo;
//        }
        // isAuthenticated()可以判断是否认证成功
        // ShiroFilter也是根据这个值来做过滤
        boolean authenticated = subject.isAuthenticated();

        // 获取Session
        Session session = subject.getSession();


        //subject.getPrincipals().getPrimaryPrincipal()来获取AuthenticationInfo中封装的Principal信息
        MarketAdmin marketAdmin = (MarketAdmin) subject.getPrincipals().getPrimaryPrincipal();

        session.setAttribute("info", marketAdmin);

        LoginUserData loginUserData = new LoginUserData();
        AdminInfoBean adminInfo = new AdminInfoBean();
//        adminInfo.setAvatar("https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif");
//        adminInfo.setNickName("admin123");
        // 封装登陆用户的信息返回
        adminInfo.setAvatar(marketAdmin.getAvatar());
        adminInfo.setNickName(marketAdmin.getUsername());
        loginUserData.setAdminInfo(adminInfo);
//        loginUserData.setToken("c4d988f3-e4c5-4e46-b6ce-13b9e008ea20");
        // 封装SessionId作为Token返回
        loginUserData.setToken((String) session.getId());
        return BaseRespVo.ok(loginUserData);
    }

    @PostMapping("logout")
    public BaseRespVo<LoginUserData> logout() {
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        return BaseRespVo.ok();
    }


    @RequestMapping("info")
    public BaseRespVo info(String token) {

        Subject subject = SecurityUtils.getSubject();
        Session session = subject.getSession();
        String sessionId = (String) session.getId();

        if (!StringUtils.equals(sessionId, token)) {
            return BaseRespVo.invalidParameter("token已失效，请重新登陆");
        }

        MarketAdmin marketAdmin = (MarketAdmin) session.getAttribute("info");

        //开发完shiro之后，再整合
        InfoData infoData = new InfoData();
//        infoData.setName("admin123");
        infoData.setName(marketAdmin.getUsername());

        //根据primaryPrincipal做查询
//        infoData.setAvatar("https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif");
        infoData.setAvatar(marketAdmin.getAvatar());
        ArrayList<String> roles = new ArrayList<>();
//        perms.add("*");
        Integer[] roleIds = marketAdmin.getRoleIds();
        for (Integer roleId : roleIds) {
            // 根据id去查name
            MarketRole marketRole = marketRoleMapper.selectByPrimaryKey(roleId);
            roles.add(marketRole.getName());

        }

        // 查权限
        ArrayList<String> perms = new ArrayList<>();
        // 防止不同角色之间的权限重复，用一个Set来装
        HashSet<String> permSet = new HashSet<>();
        for (Integer roleId : roleIds) {
            // 根据id去查权限
            MarketPermissionExample example = new MarketPermissionExample();
            example.createCriteria().andRoleIdEqualTo(roleId);
            List<MarketPermission> marketPermissions = marketPermissionMapper.selectByExample(example);
            // * 超级管理员的处理
            if (marketPermissions.size() == 1 && "*".equals(marketPermissions.get(0).getPermission())) {
                perms.clear();
                perms.add("*");
                break;
            }
            // 正常管理员的处理
            // 防止重复，用一个Set来装
            for (MarketPermission marketPermission : marketPermissions) {
                String permission = marketPermission.getPermission();
                permSet.add(permission);
            }

        }
        // 再遍历集合去查对应的api
        for (String permission : permSet) {
            MarketAdminPermissionExample example = new MarketAdminPermissionExample();
            example.createCriteria().andApiIdEqualTo(permission);
            List<MarketAdminPermission> marketAdminPermissions = marketAdminPermissionMapper.selectByExample(example);
            for (MarketAdminPermission marketAdminPermission : marketAdminPermissions) {
                perms.add(marketAdminPermission.getApi());
            }
        }

//        roles.add("超级管理员");
        infoData.setRoles(roles);
        infoData.setPerms(perms);
        return BaseRespVo.ok(infoData);
    }
}
